<template>
	<div class="modern-file-preview">
		<!-- 全屏预览遮罩层 -->
		<transition name="preview-fade">
			<div v-if="visible" class="preview-overlay" @click.self="closePreview" @keydown.esc="closePreview" tabindex="-1">
				<!-- 主预览容器 -->
				<div class="preview-container">
					<!-- 顶部工具栏 -->
					<div class="preview-toolbar">
						<!-- 左侧文件信息 -->
						<div class="toolbar-section toolbar-left">
							<div class="file-info">
								<div class="file-icon">
									<i class="fa" :class="getFileIcon(currentFile)"></i>
								</div>
								<div class="file-details">
									<div class="file-name">{{ getCurrentFileName() }}</div>
									<div class="file-meta">
										<span class="file-type">{{ getFileType(currentFile) }}</span>
										<span class="file-separator">•</span>
										<span class="file-size">{{ getFileSize(currentFile) }}</span>
										<span v-if="files.length > 1" class="file-separator">•</span>
										<span v-if="files.length > 1" class="file-counter"> {{ currentIndex + 1 }} / {{ files.length }} </span>
									</div>
								</div>
							</div>
						</div>

						<!-- 中间导航按钮 -->
						<div v-if="files.length > 1" class="toolbar-section toolbar-center">
							<div class="navigation-buttons">
								<button
									class="nav-btn"
									:class="{ disabled: currentIndex <= 0 }"
									@click="previousFile"
									:disabled="currentIndex <= 0"
									title="上一个文件 (←)"
								>
									<i class="fa fa-chevron-left"></i>
								</button>
								<button
									class="nav-btn"
									:class="{ disabled: currentIndex >= files.length - 1 }"
									@click="nextFile"
									:disabled="currentIndex >= files.length - 1"
									title="下一个文件 (→)"
								>
									<i class="fa fa-chevron-right"></i>
								</button>
							</div>
						</div>

						<!-- 右侧操作按钮 -->
						<div class="toolbar-section toolbar-right">
							<div class="action-buttons">
								<button class="action-btn download-btn" @click="downloadFile" title="下载文件">
									<i class="fa fa-download"></i>
								</button>
								<button class="action-btn close-btn" @click="closePreview" title="关闭预览 (ESC)">
									<i class="fa fa-times"></i>
								</button>
							</div>
						</div>
					</div>

					<!-- 预览内容区域 -->
					<div class="preview-content">
						<!-- 图片预览 -->
						<div v-if="isImage(currentFile)" class="image-preview">
							<!-- 加载状态覆盖层 -->
							<div v-if="isLoading" class="preview-loading-overlay">
								<div class="loading-spinner">
									<i class="fa fa-spinner fa-spin"></i>
								</div>
								<div class="loading-text">{{ props.externalLoading ? '正在加载文件信息...' : '文件加载中...' }}</div>
							</div>

							<!-- 图片元素始终渲染，但可能被loading覆盖 -->
							<img
								:src="getFileUrl(currentFile)"
								:alt="getCurrentFileName()"
								@load="onFileLoaded"
								@error="onFileError"
								class="preview-image"
								:class="{ loading: isLoading }"
								:key="getFileUrl(currentFile)"
							/>
						</div>

						<!-- PDF预览 -->
						<div v-else-if="isPdf(currentFile)" class="pdf-preview">
							<!-- 加载状态覆盖层 -->
							<div v-if="isLoading" class="preview-loading-overlay">
								<div class="loading-spinner">
									<i class="fa fa-spinner fa-spin"></i>
								</div>
								<div class="loading-text">{{ props.externalLoading ? '正在加载文件信息...' : '文件加载中...' }}</div>
							</div>

							<!-- PDF iframe始终渲染 -->
							<iframe
								:src="getPdfUrl(currentFile)"
								class="pdf-frame"
								:class="{ loading: isLoading }"
								@load="onFileLoaded"
								@error="onFileError"
							></iframe>

							<div v-if="loadError" class="preview-error">
								<div class="error-icon">
									<i class="fa fa-file-pdf-o"></i>
								</div>
								<div class="error-message">
									<h3>PDF预览失败</h3>
									<p>此PDF文件无法在浏览器中预览，请下载后查看</p>
								</div>
								<button class="download-btn-large" @click="downloadFile">
									<i class="fa fa-download"></i>
									下载PDF文件
								</button>
							</div>
						</div>

						<!-- 不支持的文件类型 -->
						<div v-else-if="!isLoading" class="unsupported-preview">
							<div class="unsupported-content">
								<div class="unsupported-icon">
									<i class="fa" :class="getFileIcon(currentFile)"></i>
								</div>
								<div class="unsupported-message">
									<h3>{{ getFileType(currentFile) }} 文件</h3>
									<p>此文件类型不支持在线预览</p>
									<p class="hint">您可以下载文件到本地进行查看</p>
								</div>
								<button class="download-btn-large" @click="downloadFile">
									<i class="fa fa-download"></i>
									下载文件
								</button>
							</div>
						</div>

						<!-- 文件加载错误 -->
						<div v-if="!isLoading && loadError && !isPdf(currentFile)" class="preview-error">
							<div class="error-icon">
								<i class="fa fa-exclamation-triangle"></i>
							</div>
							<div class="error-message">
								<h3>文件加载失败</h3>
								<p>无法加载此文件，请检查文件是否存在或网络连接</p>
							</div>
							<button class="download-btn-large" @click="downloadFile">
								<i class="fa fa-download"></i>
								重新下载
							</button>
						</div>
					</div>
				</div>
			</div>
		</transition>
	</div>
</template>

<script setup>
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue';

// Props
const props = defineProps({
	visible: {
		type: Boolean,
		default: false,
	},
	files: {
		type: Array,
		default: () => [],
	},
	currentIndex: {
		type: Number,
		default: 0,
	},
	downloadHandler: {
		type: Function,
		default: null,
	},
	// 外部loading状态（用于接口调用时）
	externalLoading: {
		type: Boolean,
		default: false,
	},
});

// Emits
const emit = defineEmits(['update:visible', 'update:currentIndex', 'download']);

// Reactive data
const loading = ref(false);
const loadError = ref(false);
const loadTimeout = ref(null);

// Computed
const currentFile = computed(() => props.files[props.currentIndex] || {});

// 合并内部loading和外部loading状态
const isLoading = computed(() => props.externalLoading || loading.value);

// Methods
const getCurrentFileName = () => {
	return currentFile.value?.FileName || currentFile.value?.Name || currentFile.value?.name || currentFile.value?.fileName || '未知文件';
};

const getFileType = (file) => {
	const fileName = file?.FileName || file?.Name || file?.name || file?.fileName;
	if (!fileName) return '未知';
	const ext = fileName.split('.').pop()?.toUpperCase();
	return ext || '未知';
};

const getFileSize = (file) => {
	const size = file?.FileSize || file?.Size || 0;
	if (size < 1024) return `${size} B`;
	if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`;
	if (size < 1024 * 1024 * 1024) return `${(size / (1024 * 1024)).toFixed(1)} MB`;
	return `${(size / (1024 * 1024 * 1024)).toFixed(1)} GB`;
};

const getFileIcon = (file) => {
	const fileName = file?.FileName || file?.Name || file?.name || file?.fileName;
	if (!fileName) return 'fa-file-o';
	const ext = fileName.split('.').pop()?.toLowerCase();

	const iconMap = {
		// 图片
		jpg: 'fa-file-image-o',
		jpeg: 'fa-file-image-o',
		png: 'fa-file-image-o',
		gif: 'fa-file-image-o',
		bmp: 'fa-file-image-o',
		webp: 'fa-file-image-o',

		// 文档
		pdf: 'fa-file-pdf-o',
		doc: 'fa-file-word-o',
		docx: 'fa-file-word-o',
		xls: 'fa-file-excel-o',
		xlsx: 'fa-file-excel-o',
		ppt: 'fa-file-powerpoint-o',
		pptx: 'fa-file-powerpoint-o',
		txt: 'fa-file-text-o',

		// 压缩包
		zip: 'fa-file-archive-o',
		rar: 'fa-file-archive-o',
		'7z': 'fa-file-archive-o',

		// 音视频
		mp3: 'fa-file-audio-o',
		wav: 'fa-file-audio-o',
		mp4: 'fa-file-video-o',
		avi: 'fa-file-video-o',
		mov: 'fa-file-video-o',

		// 代码
		js: 'fa-file-code-o',
		css: 'fa-file-code-o',
		html: 'fa-file-code-o',
		vue: 'fa-file-code-o',
		py: 'fa-file-code-o',
		java: 'fa-file-code-o',
	};

	return iconMap[ext] || 'fa-file-o';
};

const isImage = (file) => {
	const fileName = file?.FileName || file?.Name || file?.name || file?.fileName;
	if (!fileName) return false;
	const ext = fileName.split('.').pop()?.toLowerCase();
	return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'].includes(ext);
};

const isPdf = (file) => {
	const fileName = file?.FileName || file?.Name || file?.name || file?.fileName;
	if (!fileName) return false;
	const ext = fileName.split('.').pop()?.toLowerCase();
	return ext === 'pdf';
};

const getFileUrl = (file) => {
	// 支持多种文件URL字段
	const directUrl = file?.Url || file?.LocalUrl || file?.PreviewUrl || file?.url || file?.FileUrl;
	if (directUrl) {
		return directUrl;
	}

	// 如果没有直接的URL但有FileId，则动态生成URL
	if (file?.FileId) {
		return `/api/_file/getfile/${file.FileId}`;
	}

	return '';
};

const getPdfUrl = (file) => {
	const url = getFileUrl(file);
	// 添加PDF预览参数
	return `${url}#view=FitH&toolbar=0&navpanes=0`;
};

const previousFile = () => {
	if (props.currentIndex > 0) {
		emit('update:currentIndex', props.currentIndex - 1);
	}
};

const nextFile = () => {
	if (props.currentIndex < props.files.length - 1) {
		emit('update:currentIndex', props.currentIndex + 1);
	}
};

const downloadFile = () => {
	if (props.downloadHandler) {
		props.downloadHandler(currentFile.value);
	} else {
		emit('download', currentFile.value);
	}
};

const closePreview = () => {
	emit('update:visible', false);
};

const onFileLoaded = () => {
	// 清除超时定时器
	if (loadTimeout.value) {
		clearTimeout(loadTimeout.value);
		loadTimeout.value = null;
	}
	loading.value = false;
	loadError.value = false;
};

const onFileError = () => {
	// 清除超时定时器
	if (loadTimeout.value) {
		clearTimeout(loadTimeout.value);
		loadTimeout.value = null;
	}
	loading.value = false;
	loadError.value = true;
};

// 开始加载文件的函数
const startFileLoading = () => {
	const file = currentFile.value;
	const needsLoading = isImage(file) || isPdf(file);

	if (needsLoading) {
		loading.value = true;
		loadError.value = false;

		// 设置10秒超时，防止无限加载
		loadTimeout.value = setTimeout(() => {
			loading.value = false;
			loadError.value = true;
		}, 10000);
	} else {
		loading.value = false;
		loadError.value = false;
	}
};

// 键盘事件处理
const handleKeydown = (e) => {
	if (!props.visible) return;

	switch (e.key) {
		case 'Escape':
			closePreview();
			break;
		case 'ArrowLeft':
			e.preventDefault();
			previousFile();
			break;
		case 'ArrowRight':
			e.preventDefault();
			nextFile();
			break;
	}
};

// 监听文件变化
watch(
	() => props.currentIndex,
	() => {
		// 清除之前的超时定时器
		if (loadTimeout.value) {
			clearTimeout(loadTimeout.value);
			loadTimeout.value = null;
		}

		// 只在不是外部loading时才设置内部loading
		if (!props.externalLoading) {
			startFileLoading();
		}
	}
);

watch(
	() => props.visible,
	(newVal) => {
		if (newVal) {
			// 只在不是外部loading时才设置内部loading
			if (!props.externalLoading) {
				startFileLoading();
			}
			nextTick(() => {
				// 自动聚焦以接收键盘事件
				const overlay = document.querySelector('.preview-overlay');
				if (overlay) overlay.focus();
			});
		} else {
			// 关闭预览时清除定时器
			if (loadTimeout.value) {
				clearTimeout(loadTimeout.value);
				loadTimeout.value = null;
			}
		}
	}
);

// 监听外部loading状态变化
watch(
	() => props.externalLoading,
	(newVal) => {
		if (!newVal && props.visible) {
			// 外部loading结束时，开始文件加载
			startFileLoading();
		}
	}
);

// 生命周期
onMounted(() => {
	document.addEventListener('keydown', handleKeydown);
});

onUnmounted(() => {
	document.removeEventListener('keydown', handleKeydown);
	// 清理定时器
	if (loadTimeout.value) {
		clearTimeout(loadTimeout.value);
		loadTimeout.value = null;
	}
});
</script>

<style scoped>
/* 现代化文件预览样式 */
.modern-file-preview {
	position: relative;
}

/* 预览遮罩层 */
.preview-overlay {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: rgba(0, 0, 0, 0.75);
	backdrop-filter: blur(4px);
	z-index: 9999;
	display: flex;
	align-items: center;
	justify-content: center;
	outline: none;
}

/* 主预览容器 */
.preview-container {
	position: relative;
	width: 100vw;
	height: 100vh;
	display: flex;
	flex-direction: column;
}

/* 顶部工具栏 */
.preview-toolbar {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	z-index: 1000;
	background: linear-gradient(180deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.4) 100%);
	backdrop-filter: blur(10px);
	padding: 20px 32px;
	display: flex;
	justify-content: space-between;
	align-items: center;
	transition: all 0.3s ease;
}

.preview-toolbar:hover {
	background: linear-gradient(180deg, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.6) 100%);
}

/* 工具栏区域 */
.toolbar-section {
	display: flex;
	align-items: center;
}

.toolbar-left {
	flex: 1;
	justify-content: flex-start;
}

.toolbar-center {
	flex: 0 0 auto;
}

.toolbar-right {
	flex: 1;
	justify-content: flex-end;
}

/* 文件信息 */
.file-info {
	display: flex;
	align-items: center;
	gap: 12px;
}

.file-icon {
	width: 40px;
	height: 40px;
	background: rgba(255, 255, 255, 0.1);
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	backdrop-filter: blur(10px);
}

.file-icon i {
	font-size: 18px;
	color: #fff;
}

.file-details {
	flex: 1;
}

.file-name {
	font-size: 16px;
	font-weight: 600;
	color: #fff;
	margin-bottom: 4px;
	max-width: 300px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.file-meta {
	display: flex;
	align-items: center;
	gap: 6px;
	font-size: 13px;
	color: rgba(255, 255, 255, 0.8);
}

.file-separator {
	color: rgba(255, 255, 255, 0.5);
}

/* 导航按钮 */
.navigation-buttons {
	display: flex;
	gap: 12px;
}

.nav-btn {
	width: 48px;
	height: 48px;
	background: rgba(255, 255, 255, 0.1);
	border: 1px solid rgba(255, 255, 255, 0.2);
	border-radius: 50%;
	color: #fff;
	cursor: pointer;
	transition: all 0.3s ease;
	display: flex;
	align-items: center;
	justify-content: center;
}

.nav-btn:hover:not(.disabled) {
	background: rgba(255, 255, 255, 0.2);
	border-color: rgba(255, 255, 255, 0.3);
	transform: scale(1.05);
}

.nav-btn.disabled {
	opacity: 0.3;
	cursor: not-allowed;
}

.nav-btn i {
	font-size: 16px;
}

/* 操作按钮 */
.action-buttons {
	display: flex;
	gap: 12px;
}

.action-btn {
	width: 44px;
	height: 44px;
	background: rgba(255, 255, 255, 0.1);
	border: 1px solid rgba(255, 255, 255, 0.2);
	border-radius: 50%;
	color: #fff;
	cursor: pointer;
	transition: all 0.3s ease;
	display: flex;
	align-items: center;
	justify-content: center;
}

.action-btn:hover {
	transform: scale(1.05);
}

.download-btn:hover {
	background: rgba(64, 158, 255, 0.8);
	border-color: #409eff;
}

.close-btn:hover {
	background: rgba(245, 108, 108, 0.8);
	border-color: #f56c6c;
}

.action-btn i {
	font-size: 14px;
}

/* 预览内容区域 */
.preview-content {
	flex: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 80px 20px 20px;
	position: relative;
}

/* 加载状态 */
.preview-loading {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 16px;
	color: rgba(255, 255, 255, 0.8);
}

/* 加载状态覆盖层 */
.preview-loading-overlay {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: rgba(0, 0, 0, 0.6);
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 16px;
	color: rgba(255, 255, 255, 0.9);
	z-index: 10;
	border-radius: 8px;
}

.loading-spinner i {
	font-size: 48px;
	color: #409eff;
}

.loading-text {
	font-size: 16px;
	margin: 0;
}

/* 图片预览 */
.image-preview {
	width: 100%;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
}

.preview-image {
	max-width: 100%;
	max-height: 100%;
	border-radius: 8px;
	box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
	transition: all 0.3s ease;
	cursor: zoom-in;
}

.preview-image:hover {
	transform: scale(1.02);
}

/* PDF预览 */
.pdf-preview {
	width: 100%;
	height: 100%;
	position: relative;
	background: #fff;
	border-radius: 8px;
	overflow: hidden;
	box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
	margin: 0 40px;
}

.pdf-frame {
	width: 100%;
	height: 100%;
	border: none;
}

/* 不支持的文件预览 */
.unsupported-preview {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
}

.unsupported-content {
	text-align: center;
	max-width: 500px;
	padding: 60px 40px;
	background: rgba(255, 255, 255, 0.05);
	border-radius: 16px;
	backdrop-filter: blur(10px);
	border: 1px solid rgba(255, 255, 255, 0.1);
}

.unsupported-icon {
	margin-bottom: 24px;
}

.unsupported-icon i {
	font-size: 80px;
	color: #409eff;
	opacity: 0.8;
}

.unsupported-message h3 {
	font-size: 24px;
	font-weight: 600;
	color: #fff;
	margin: 0 0 12px 0;
}

.unsupported-message p {
	font-size: 16px;
	color: rgba(255, 255, 255, 0.7);
	margin: 0 0 8px 0;
	line-height: 1.5;
}

.unsupported-message .hint {
	font-size: 14px;
	color: rgba(255, 255, 255, 0.5);
	margin-bottom: 24px;
}

/* 错误状态 */
.preview-error {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 24px;
	color: rgba(255, 255, 255, 0.8);
	text-align: center;
	max-width: 500px;
	padding: 40px;
}

.error-icon i {
	font-size: 64px;
	color: #f56c6c;
}

.error-message h3 {
	font-size: 20px;
	font-weight: 600;
	color: #fff;
	margin: 0 0 8px 0;
}

.error-message p {
	font-size: 14px;
	color: rgba(255, 255, 255, 0.7);
	margin: 0;
	line-height: 1.5;
}

/* 大下载按钮 */
.download-btn-large {
	padding: 16px 32px;
	font-size: 16px;
	font-weight: 500;
	background: #409eff;
	border: 1px solid #409eff;
	border-radius: 12px;
	color: #fff;
	cursor: pointer;
	transition: all 0.3s ease;
	display: flex;
	align-items: center;
	gap: 8px;
}

.download-btn-large:hover {
	background: #66b1ff;
	border-color: #66b1ff;
	transform: translateY(-2px);
	box-shadow: 0 8px 25px rgba(64, 158, 255, 0.3);
}

.download-btn-large i {
	font-size: 16px;
}

/* 动画效果 */
.preview-fade-enter-active,
.preview-fade-leave-active {
	transition: all 0.3s ease;
}

.preview-fade-enter-from,
.preview-fade-leave-to {
	opacity: 0;
	transform: scale(0.95);
}

.preview-fade-enter-to,
.preview-fade-leave-from {
	opacity: 1;
	transform: scale(1);
}

/* 响应式设计 */
@media (max-width: 768px) {
	.preview-toolbar {
		padding: 16px 20px;
	}

	.file-name {
		font-size: 14px;
		max-width: 200px;
	}

	.file-meta {
		font-size: 12px;
	}

	.nav-btn {
		width: 40px;
		height: 40px;
	}

	.action-btn {
		width: 36px;
		height: 36px;
	}

	.preview-content {
		padding: 70px 15px 15px;
	}

	.pdf-preview {
		margin: 0 15px;
	}

	.unsupported-content {
		padding: 40px 20px;
		margin: 20px;
	}

	.unsupported-icon i {
		font-size: 60px;
	}

	.unsupported-message h3 {
		font-size: 20px;
	}

	.unsupported-message p {
		font-size: 14px;
	}

	.download-btn-large {
		padding: 12px 24px;
		font-size: 14px;
	}
}

@media (max-width: 480px) {
	.preview-toolbar {
		padding: 12px 16px;
	}

	.file-icon {
		width: 32px;
		height: 32px;
	}

	.file-icon i {
		font-size: 14px;
	}

	.file-name {
		font-size: 13px;
		max-width: 150px;
	}

	.nav-btn {
		width: 36px;
		height: 36px;
	}

	.action-btn {
		width: 32px;
		height: 32px;
	}

	.action-btn i {
		font-size: 12px;
	}
}
</style>
